﻿#include <iostream>
using namespace std;

//隐式转换的弊端，可能随时发生类型提升或者类型截断且难以跟踪错误的转换，进而影响预期效果
void Insert(size_t pos, char ch)
{
    size_t _size = 5;
    //....
    int end = _size - 1;
    // end 隐式类型转换，提升为无符号整型，当pos为0时，死循环
    while (end >= pos) 
    {
        //_str[end + 1] = _str[end];
        --end;
    }
}

//int main()
//{
//    int i = 1;
//    //隐式类型转换，用 i 拷贝一个double临时变量赋值给d 
//    //（意义相近的类型，都是用来存储数据大小）
//    double d = i;
//    printf("%d, %.2f\n", i, d);
//
//
//    //显示的强制类型转换，用于意义不相近的类型，但其值转换后有意义
//    //且值与值之间存在联系，比如地址的值也是一串数字编号，也可以看作数据大小的范畴
//    int* p = &i;
//    int address = (int)p;
//    printf("%x, %d\n", p, address);
//
//
//    //隐式转换的弊端案例
//    Insert(5, 'a');
//    Insert(0, 'b');
//
//    return 0;
//}

// 针对C风格的转换格式的不少缺点：
// 1. 隐式类型转化有些情况下可能会出问题：比如数据精度丢失
// 2. 显式类型转换将所有情况混合在一起，代码不够清晰
// C++引入了四种命名的强制类型转换操作符：static_cast、reinterpret_cast、const_cast、dynamic_cast
//int main()
//{
//    //1、static_cast用于具有相近意义的数据类型的隐式转换
//    double d = 1.11;
//    int a = static_cast<int>(d);
//    cout << a << endl;
//
//
//    int* p = &a;
//    //一个是地址上的意义，一个是数据大小的意义，不相近，static_cast不支持转换
//    //int address = static_cast<int>(p);
//
//    //2、reinterpret_cast 用于值转换后有意义的显示强制类型转换
//    int address = reinterpret_cast<int>(p);
//
//
//    //const_cast最常用的用途就是删除变量的const属性，方便权限提升方面的赋值
//    const int a2 = 2;
//    int* p2 = const_cast<int*>(&a2);
//    //int* p2 = (int*)(&a2);    //也可以兼容
//    *p2 = 20;
//
//    //vs对于const常量的处理方式：
//    //编译器认为const类型的变量往往是不被修改的，因此将其存储在寄存器上或cache缓存
//    //虽然内存中的a变量已经被修改为20，但编译器读取变量a的时候是从寄存器中直接读取
//    //并没有从内存中读取，换言之，编译器不知道内存中的 a 的值已经被修改了
//    cout << a2 << endl;        //2
//    cout << *p2 << endl;       //20
//
//
//    // volatile，示意编译器每次都从从内存中读取变量 a
//    volatile const int a3 = 2;
//    int* p3 = const_cast<int*>(&a3);
//    *p3 = 20;
//    cout << a3 << endl;        //20
//    cout << *p3 << endl;       //20
//
//    return 0;
//}


//class A
//{
//public:
//	virtual void f(){}
//
//public:
//	int _a = 0;
//};
//
//class B : public A
//{
//public:
//	int _b = 1;
//};
//
//void Func(A* pa)
//{
//    // pa可能指向父类，也可能指向子类，但我们无法判断
//    // 如果pa指向父类，然后直接将父类指针强制类型转换，赋值给子类指针
//    // 可能会访问到不属于父类的子类范围的数据（越界问题），因此直接强转是不安全的
//    //B* pb = (B*)pa;
//    //pb->_a++;
//    //pb->_b++;   //可能越界
//
//
//    // 如果pa是指向子类，那么可以转换，转换表达式返回正确的地址
//	// 如果pa是指向父类，那么不能转换，转换表达式返回nullptr
//    // dynamic_cast只能用于父类含有虚函数的类（即实现多态的类）
//    B* pb = dynamic_cast<B*>(pa);   //安全，不会有越界情况
//    if (pb)
//    {
//        cout << "转换成功" << endl;
//		pb->_a++;
//		pb->_b++;
//		cout << pb->_a << ":" << pb->_b << endl;
//    }
//    else
//    {
//        cout << "转换失败" << endl;
//        pa->_a++;
//        cout << pa->_a << endl;
//    }
//}
//
//int main()
//{
//    A aa;
//    B bb;
//
//    //父类对象无论如何都是无法转换成子类对象的
//    //bb = (B)aa;
//
//    Func(&aa);  
//    Func(&bb);  
//
//    return 0;
//}

class A1
{
public:
    virtual void f(){}
public:
    int _a1 = 0;
};

class A2
{
public:
    virtual void f(){}
public:
    int _a2 = 0;
};

class B : public A1, public A2
{
public:
    int _b = 1;
};

int main()
{
    B bb;
    A1* p1 = &bb;
    A2* p2 = &bb;
    cout << p1 << endl;
    cout << p2 << endl << endl;

    B* pb1 = (B*)p1;
    B* pb2 = (B*)p2;
    cout << pb1 << endl;
    cout << pb2 << endl << endl;

    B* pb3 = dynamic_cast<B*>(p1);
    B* pb4 = dynamic_cast<B*>(p2);
    cout << pb3 << endl;
    cout << pb4 << endl << endl;


    A1 aa1;
    A2 aa2;
    A1* pa1 = &aa1;
    A2* pa2 = &aa2;
    B* pb5 = dynamic_cast<B*>(pa1);  //指针指向父类，转换失败，返回nullptr
    B* pb6 = dynamic_cast<B*>(pa2);  //指针指向父类，转换失败，返回nullptr
    cout << pb5 << endl;    
    cout << pb6 << endl << endl;

    return 0;
}


